package com.gitee.itembucket.util.germ

import com.germ.germplugin.api.dynamic.gui.GermGuiScreen
import com.gitee.itembucket.util.germ.germ.GermPartDSL
import com.gitee.itembucket.util.germ.germ.GermScreenDSL
import org.bukkit.entity.Player
import taboolib.library.configuration.ConfigurationSection
import java.util.*
import java.util.function.Consumer

var types = mutableMapOf<String, Class<out GermPartDSL<*>>>(
    "texture" to GermTextureDSL::class.java,
    "label" to GermLabelDSL::class.java,
    "checkbox" to GermCheckBoxDSL::class.java,
    "button" to GermButtonDSL::class.java,
    "item" to GermItemDSL::class.java,
    "slot" to GermSlotDSL::class.java,
    "canvas" to GermCanvasDSL::class.java,
    "scroll" to GermScrollDSL::class.java,
    "entity" to GermEntityDSL::class.java,
    "input" to GermInputDSL::class.java,
)

fun createGUI(consumer: Consumer<GermScreenDSL>): GermGuiScreen {
    val screenDSL = GermScreenDSL()
    consumer.accept(screenDSL)
    return screenDSL.create()
}

fun createGUI(viewer: Player? = null, consumer: Consumer<GermScreenDSL>): GermGuiScreen {
    val screenDSL = GermScreenDSL()
    consumer.accept(screenDSL)
    return screenDSL.create().also {
        screenDSL.map.forEach { (key, value) -> it.simpleMap.put(key, value) }
        if (viewer != null) it.openGui(viewer)
    }
}

fun createHUD(viewer: Player, consumer: Consumer<GermScreenDSL>): GermGuiScreen {
    return createGUI(null, consumer).also {
        it.openHud(viewer)
    }
}

inline fun <reified T : GermPartDSL<*>> createDSL(consumer: Consumer<T>? = null): T {
    return T::class.java.newInstance().apply { consumer?.accept(this) }
}

inline fun <reified T> createDSL(config: ConfigurationSection, consumer: Consumer<T>? = null): T {
    return createDSL(config.getString("type")!!) {
        it as GermPartDSL<*>
        it.infuse(config)
        consumer?.accept(it)
    }
}

inline fun <reified T> createDSL(name: String, consumer: Consumer<T>? = null): T {
    val germPartDSL = types[name]?.newInstance() ?: error("Not type '$name'")
    consumer?.accept(germPartDSL as T)
    return germPartDSL as T
}

fun createTemplate(name: String, config: ConfigurationSection, consumer: (GermPartDSL<*>,ConfigurationSection) -> Unit): GermPartDSL<*> {
    val section = config.getConfigurationSection("scrollableParts.$name")!!
    return createDSL(section) {
        it.name = UUID.randomUUID().toString()
        consumer(it,section)
    }
}

fun <T> createTemplates(config: ConfigurationSection, elements: List<T>, consumer: (GermPartDSL<*>,Int,T) -> Unit) : List<GermPartDSL<*>> {
    return elements.mapIndexed { index, t ->
        createDSL(config) {
            it.sort(index)
            consumer(it,index,t)
        }
    }
}

fun GermPartDSL<*>.sort(index: Int) {
    locationX = locationX.replace("{index}",index.toString())
    locationY = locationY.replace("{index}",index.toString())
    locationZ = locationZ.replace("{index}",index.toString())
}

fun <T> createTemplates(
    name: String,
    config: ConfigurationSection,
    elements: List<T>,
    consumer: (GermPartDSL<*>, Int, T,ConfigurationSection) -> Unit
): List<GermPartDSL<*>> {
    return elements.mapIndexed { index, t ->
        createTemplate(name, config) { dsl,conf ->
            dsl.sort(index)
            consumer(dsl, index, t,conf)
        }
    }
}